home *** CD-ROM | disk | FTP | other *** search
- #include <math.h>
- #include "skeleton.h"
-
- /* animate primitives */
-
- int strokes(line_ptr line)
- {
- int n;
-
- n = 1;
- while(line->next!=NULL)
- {
- n++;
- line = line->next;
- }
-
- return(n);
- }
-
- void addsegs(line_ptr seg,int n,int req)
- {
- int rs,rt,i,j,k=0,l;
- int x1,y1,dx,dy;
-
- if(n/POINTS != req/POINTS)
- seg->pts=(struct pts *)realloc((void *)seg->pts,
- sizeof(struct pts)*POINTS*(req/POINTS+1),
- sizeof(struct pts)*POINTS*(n/POINTS+1));
- seg->number = req+1;
-
- if(n==0)
- {
- x1 = seg->pts->p[0][0];
- y1 = seg->pts->p[0][1];
-
-
- for(i=1;i<=req;i++)
- {
- seg->pts->p[i][0]=x1;
- seg->pts->p[i][1]=y1;
- }
- return;
- }
-
- rt = req/n;
- rs = req%n;
-
- for(i=n;i>=0;i--)
- {
- if(i>rs)
- j = rs + rt*i;
- else
- j = (rt+1)*i;
-
- seg->pts->p[j][0] = seg->pts->p[i][0];
- seg->pts->p[j][1] = seg->pts->p[i][1];
-
-
- if(i!=n)
- {
- x1 = seg->pts->p[j][0];
- y1 = seg->pts->p[j][1];
- dx = seg->pts->p[k][0] - seg->pts->p[j][0];
- dy = seg->pts->p[k][1] - seg->pts->p[j][1];
-
- for(l=1;l<k-j;l++)
- {
- seg->pts->p[j+l][0] = (dx*l)/(k-j)+x1;
- seg->pts->p[j+l][1] = (dy*l)/(k-j)+y1;
-
- }
- }
- k = j;
- }
- }
-
- void breakstroke(line_ptr seg,int n)
- {
- int step;
- line_ptr newseg;
-
-
- if(n<=1) return;
-
- if(seg->number-1<n)
- addsegs(seg,seg->number-1,n);
-
- step = (seg->number-1)/n;
-
- for(;n>1;n--)
- {
- newseg = cutseg(seg,step);
-
- newseg->next = seg->next;
- seg->next = newseg;
-
- seg = newseg;
- }
- }
-
- void addstrokes(line_ptr line,int n,int req)
- {
- int rs,rt,i;
- line_ptr nextline;
-
- rt = req/n;
- rs = req%n;
-
- for(i=1;i<=rs;i++)
- {
- nextline = line->next;
- breakstroke(line,rt+1);
- line = nextline;
- }
- while(line!=NULL)
- {
- nextline = line->next;
- breakstroke(line,rt);
- line = nextline;
- }
- }
-
-
- void preprocess(line_ptr l1,line_ptr l2)
- {
- int n1,n2;
-
- if((l1==NULL)||(l2==NULL)) return;
-
-
- n1 = strokes(l1);
- n2 = strokes(l2);
-
- if(n1>n2) addstrokes(l2,n2,n1);
- else if(n2>n1) addstrokes(l1,n1,n2);
-
- while(l1!=NULL)
- {
- n1 = l1->number-1;
- n2 = l2->number-1;
-
- if(n1>n2) addsegs(l2,n2,n1);
- else if(n2>n1) addsegs(l1,n1,n2);
-
- l1 = l1->next;
- l2 = l2->next;
- }
- }
-
- int relative(int x ,int y ,int x1,int y1,int x2,int y2,
- int x3,int y3,int x4,int y4,int *l,int *w)
- {
- double L,W,dist2,tdist2;
- int a,b,c,d,e,f,g,h;
- int A,B,C;
- int temp,cross1,cross2;
-
- a = x-x1; b = x2-x1; c = y-y1; d = y2-y1;
- e = x-x3; f = x4-x3; g = y-y3; h = y4-y3;
-
- cross1 = a*d - c*b; /* psuedo cross products */
- cross2 = e*h - g*f;
-
- if((cross1>0 && cross2>0)||(cross1<0 && cross2<0))
- return(FALSE);
-
- cross1 = (a-e)*c - (c-g)*a; /* another cross product */
- cross2 = (x4-x2)*(y-y2) - (y4-y2)*(x-x2);
-
- if((cross1>0 && cross2>0)||(cross1<0 && cross2<0))
- return(FALSE);
-
- A = b*h - d*f;
- B = c*f + d*e - a*h - b*g; /* I won't soon forget this one */
- C = a*g - c*e;
-
- if(A==0)
- {
- if(B!=0)
- L = -(double)C/B;
- else
- {
- return(FALSE);
- }
- }
- else
- {
- temp = B*B - 4*A*C;
-
- if(temp<0)
- {
- return(FALSE);
- }
-
- L = ((double)(-B) - sqrt((double)temp))/(2*A);
- if(L>1.0 || L<0.0)
- L = ((double)(-B) + sqrt((double)temp))/(2*A);
- if(L>1.0 || L<0.0)
- {
- return(FALSE);
- }
- }
-
- tdist2 = (a-e-(b-f)*L)*(a-e-(b-f)*L) + (c-g-(d-h)*L)*(c-g-(d-h)*L);
- if(tdist2==0.0)
- {
- return(FALSE);
- }
- dist2 = (a-b*L)*(a-b*L) + (c-d*L)*(c-d*L);
-
- W = sqrt(dist2/tdist2);
- if(W>1.0 || W<0.0)
- {
- return(FALSE);
- }
-
- *l = (int)(L*256);
- *w = (int)(W*256);
-
- return(TRUE);
- }
-
- line_ptr makerelative(obj_ptr object)
- {
- int i,j,k,p;
- int l,w;
- line_ptr seg,rel,head;
-
- seg = object->image;
- rel = head = NULL;
-
- while(seg!=NULL)
- {
- p = 0;
- for(i=0;i<seg->number;i++)
- {
- for(j=0;j<object->skeleton->number;j++)
- {
- for(k=0;k<=1;k++)
- {
- if((j*2+k+2<object->outline->number) &&
- (j+1<object->skeleton->number))
- {
- if(relative(seg->pts->p[i][0],seg->pts->p[i][1],
- object->skeleton->pts->p[j][0],
- object->skeleton->pts->p[j][1],
- object->skeleton->pts->p[j+1][0],
- object->skeleton->pts->p[j+1][1],
- object->outline->pts->p[j*2+k][0],
- object->outline->pts->p[j*2+k][1],
- object->outline->pts->p[j*2+k+2][0],
- object->outline->pts->p[j*2+k+2][1],
- &l,&w)==TRUE)
- {
- if(rel==NULL)
- {
- rel=(line_ptr)malloc(sizeof(struct line));
- rel->pts=(struct pts *)
- malloc(sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1));
-
- head = rel;
- rel->next = NULL;
- rel->linec = seg->linec;
- rel->fillc = seg->fillc;
- }
- else if(p==0)
- {
- rel->next=(line_ptr)malloc(sizeof(struct line));
- rel = rel->next;
- rel->pts=(struct pts *)
- malloc(sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1));
-
- rel->next = NULL;
- rel->linec = seg->linec;
- rel->fillc = seg->fillc;
- }
-
- rel->pts->p[p][0] = l+(j<<8);
- rel->pts->p[p][1] = ((k)?(-1):(1))*w;
- p++;
-
- k = 1;
- j = object->skeleton->number;
- }
- }
- }
- }
- }
- if(p!=0)
- {
- rel->number=p;
- if((p-1)/POINTS!=(seg->number-1)/POINTS)
- rel->pts=(struct pts *)
- realloc((void *)rel->pts,
- sizeof(struct pts)*POINTS*((p-1)/POINTS+1),
- sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1));
- if(p==1)
- {
- rel->pts->p[1][0] = rel->pts->p[0][0];
- rel->pts->p[1][1] = rel->pts->p[0][1];
- }
- }
- seg = seg->next;
- }
- return(head);
- }
-
- void makeimage(obj_ptr object,line_ptr relative)
- {
- int i,j,k,p;
- int l,w,x1,y1,x2,y2;
- line_ptr seg,derel;
-
- seg = relative;
- derel = NULL;
- deleteline(object->image);
-
- while(seg!=NULL)
- {
- p = 0;
- for(i=0;i<seg->number;i++)
- {
- l = seg->pts->p[i][0];
- w = seg->pts->p[i][1];
-
- j = l>>8;
- k = ((w<0)?(1):(0));
-
- l = l - (j<<8);
- w = abs(w);
-
- if((j+1<object->skeleton->number) &&
- (k+j*2+2<object->outline->number))
- {
- x1 = ((object->skeleton->pts->p[j+1][0] -
- object->skeleton->pts->p[j][0]) * l)/256 +
- object->skeleton->pts->p[j][0];
- y1 = ((object->skeleton->pts->p[j+1][1] -
- object->skeleton->pts->p[j][1]) * l)/256 +
- object->skeleton->pts->p[j][1];
- x2 = ((object->outline->pts->p[j*2+k+2][0] -
- object->outline->pts->p[j*2+k][0]) * l)/256 +
- object->outline->pts->p[j*2+k][0];
- y2 = ((object->outline->pts->p[j*2+k+2][1] -
- object->outline->pts->p[j*2+k][1]) * l)/256 +
- object->outline->pts->p[j*2+k][1];
-
- x1 = ((x2-x1) * w)/256 + x1;
- y1 = ((y2-y1) * w)/256 + y1;
-
- if(derel==NULL)
- {
- derel=(line_ptr)malloc(sizeof(struct line));
- derel->pts=(struct pts *)
- malloc(sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1));
-
- derel->next = NULL;
-
- derel->linec = seg->linec;
- derel->fillc = seg->fillc;
- object->image = derel;
- }
- else if(p==0)
- {
- derel->next=(line_ptr)malloc(sizeof(struct line));
- derel = derel->next;
- derel->pts=(struct pts *)
- malloc(sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1));
-
- derel->next = NULL;
-
- derel->linec = seg->linec;
- derel->linec = seg->linec;
- derel->fillc = seg->fillc;
- }
-
- derel->pts->p[p][0] = x1;
- derel->pts->p[p][1] = y1;
-
- p++;
- }
- }
- if(p!=0)
- {
- derel->number=p;
- if((p-1)/POINTS!=(seg->number-1)/POINTS)
- derel->pts=(struct pts *)
- realloc((void *)derel->pts,
- sizeof(struct pts)*POINTS*((p-1)/POINTS+1),
- sizeof(struct pts)*POINTS*((seg->number-1)/POINTS+1));
- setbox(derel);
- if(p==1)
- {
- derel->pts->p[1][0] = derel->pts->p[0][0];
- derel->pts->p[1][1] = derel->pts->p[0][1];
- }
- }
- seg = seg->next;
- }
- }
-
- void inbetween(int xi,int yi,int xo,int yo,int frame,int frames,
- int law,int *x,int *y)
- {
- if((law & XACCEL) && (law & XDECEL))
- *x = (int)((xo-xi)*(1.0-cos((double)PI*frame/frames))/2)+xi;
- else if(law & XACCEL)
- *x = (int)((xo-xi)*(1.0-cos((double)PI*frame/frames/2)))+xi;
- else if(law & XDECEL)
- *x = (int)((xo-xi)*sin((double)PI*frame/frames/2))+xi;
- else
- *x = (int)((xo-xi)*(double)frame/frames)+xi;
-
- if((law & YACCEL) && (law & YDECEL))
- *y = (int)((yo-yi)*(1.0-cos((double)PI*frame/frames))/2)+yi;
- else if(law & YACCEL)
- *y = (int)((yo-yi)*(1.0-cos((double)PI*frame/frames/2)))+yi;
- else if(law & YDECEL)
- *y = (int)((yo-yi)*sin((double)PI*frame/frames/2))+yi;
- else
- *y = (int)((yo-yi)*(double)frame/frames)+yi;
- }
-
- line_ptr imagebetween(line_ptr linein,line_ptr lineout,
- int frame,int frames,int law)
- {
- line_ptr start, line;
- int i;
- int x,y,n;
-
- start = NULL;
-
- while(linein!=NULL && lineout!=NULL)
- {
- if(linein->number>lineout->number)
- n = lineout->number;
- else
- n = linein->number;
-
- for(i=0;i<n;i++)
- {
- inbetween(linein->pts->p[i][0],linein->pts->p[i][1],
- lineout->pts->p[i][0],lineout->pts->p[i][1],
- frame,frames,law,&x,&y);
- if(start==NULL)
- {
- line = (line_ptr)malloc(sizeof(struct line));
- line->pts = malloc(sizeof(struct pts)*POINTS*((n-1)/POINTS+1));
-
- line->linec = linein->linec;
- line->fillc = linein->fillc;
- line->next = NULL;
-
- start = line;
- }
- else if(i==0)
- {
- line->next = (line_ptr)malloc(sizeof(struct line));
- line = line->next;
- line->pts = malloc(sizeof(struct pts)*POINTS*((n-1)/POINTS+1));
-
- line->linec = linein->linec;
- line->fillc = linein->fillc;
- line->next = NULL;
- }
-
- line->pts->p[i][0] = x;
- line->pts->p[i][1] = y;
- }
-
- line->number = n;
- setbox(line);
-
- if(n==1)
- {
- line->pts->p[1][0] = line->pts->p[0][0];
- line->pts->p[1][1] = line->pts->p[0][1];
- }
-
- linein = linein->next;
- lineout = lineout->next;
- }
- return(start);
- }
-
- obj_ptr findtype(obj_ptr object,int flags,int *n)
- {
- *n = 0;
- if(flags!=0)
- {
- while((object!=NULL)&&((object->entry&flags)!=flags))
- {
- object=object->next;
- (*n)++;
- }
- }
- else
- {
- while((object!=NULL)&&(object->entry==0))
- {
- object=object->next;
- (*n)++;
- }
- }
- return(object);
- }
-
- obj_ptr findtypeback(obj_ptr object,int flags,int *n)
- {
- *n = 0;
- if(flags!=0)
- {
- while((object!=NULL)&&((object->entry&flags)!=flags))
- {
- object=object->prev;
- (*n)++;
- }
- }
- else
- {
- while((object!=NULL)&&(object->entry==0))
- {
- object=object->prev;
- (*n)++;
- }
- }
-
- return(object);
- }
-
- /*
- void makeoutline(obj_ptr with,obj_ptr without)
- {
- double length,a1i,a1f,a2i,a2f,aoi,aof;
- int x10,y10,x11,y11,x12,y12,x1o,y1o,x20,y20,x21,y21,x22,y22,x2o,y2o;
- int i;
-
- deleteline(without->outline);
- without->outline = NULL;
-
- for(i=0;i<with->outline->number;i++)
- {
- x10 = with->skeleton->pts->p[i/2][0];
- y10 = with->skeleton->pts->p[i/2][1];
- x1o = with->outline->pts->p[i][0];
- y1o = with->outline->pts->p[i][1];
- if(i>1)
- {
- x11 = with->skeleton->pts->p[i/2-1][0];
- y11 = with->skeleton->pts->p[i/2-1][1];
- }
- if(i<with->outline->number-2)
- {
- x12 = with->skeleton->pts->p[i/2+1][0];
- y12 = with->skeleton->pts->p[i/2+1][1];
- }
-
- x20 = without->skeleton->pts->p[i/2][0];
- y20 = without->skeleton->pts->p[i/2][1];
- if(i!=0)
- {
- x21 = without->skeleton->pts->p[i/2-1][0];
- y21 = without->skeleton->pts->p[i/2-1][1];
- }
- if(i!=with->outline->number-1)
- {
- x22 = without->skeleton->pts->p[i/2+1][0];
- y22 = without->skeleton->pts->p[i/2+1][1];
- }
-
- length = sqrt((double)(x10-x11)*(x10-x11) +
- (double)(y10-y11)*(y10-y11));
-
- a1i = atan2((double)(x11-x10),(double)(y11-y10));
- a2i = atan2((double)(x12-x10),(double)(y12-y10));
- aoi = atan2((double)(x1o-x10),(double)(y1o-y10));
- a1f = atan2((double)(x21-x20),(double)(y21-y20));
- a2f = atan2((double)(x22-x20),(double)(y22-y20));
-
- if(i==0)
- aof = aoi + (a2f-a2i);
- else if(i==with->outline->number-1)
- aof = aoi + (a1f-a1i);
- else
- aof = aoi + ((a1f-a1i) + (a2f-a2i))/2;
-
- x2o = x21 + (int)(length*cos(aof));
- y2o = y21 + (int)(length*sin(aof));
-
- without->outline = addpoint(without->outline,x2o,y2o);
- }
- }
-
-
- void derelative(obj_ptr firstimage,int n)
- {
- obj_ptr nextskel,image;
- int f,acc,i;
-
- nextskel = findtype(firstimage->next,SKELETON,&f);
- f = f + 1;
- acc = f;
- while(nextskel!=NULL && acc < n)
- {
- if(nextskel->entry & XOUTLINE != XOUTLINE)
- makeoutline(firstimage,nextskel);
- image = firstimage->next;
- for(i=1;i<=f;i++)
- {
- image->skeleton = imagebetween(firstimage->skeleton,
- nextskel->skeleton,i,f,firstimage->ilaw);
- image->outline = imagebetween(firstimage->outline,
- nextskel->outline,i,f,firstimage->ilaw);
- makeimage(image);
- image = image->next;
- }
- firstimage = nextskel;
- nextskel = findtype(firstimage->next,SKELETON,&f);
- acc = acc + f;
- }
- }
- */
-
- void animate(obj_ptr object)
- {
- obj_ptr firstimage, nextimage, firstskel, nextskel, image;
- line_ptr firstrel,nextrel, rel, firstcopy, nextcopy;
- int f,n,i,j;
- int skelable;
-
- if(object==NULL) return;
- firstrel = nextrel = NULL;
-
- firstimage = findtype(object,IMAGE,&f);
-
- if(firstimage==NULL) return;
-
- if((firstimage->entry&(SKELETON|XOUTLINE))==(SKELETON|XOUTLINE))
- {
- skelable=TRUE;
- firstrel = makerelative(firstimage);
- }
- else
- {
- skelable = FALSE;
- }
-
- nextimage = findtype(firstimage->next,IMAGE,&n);
-
- while(nextimage!=NULL)
- {
- if(skelable==TRUE)
- {
- if((nextimage->entry&(SKELETON|XOUTLINE))==(SKELETON|XOUTLINE))
- {
- nextrel = makerelative(nextimage);
- nextcopy = copyline(nextrel);
- firstcopy = copyline(firstrel);
- preprocess(firstcopy,nextcopy);
- }
- else
- {
- skelable = FALSE;
- }
-
- j = 0;
- firstskel = firstimage;
- nextskel = findtype(firstskel->next,SKELETON|XOUTLINE,&f);
- while((j+f<=n) && (nextskel!=NULL))
- {
- if((skelable==TRUE) && (nextskel!=nextimage))
- {
- rel = imagebetween(firstcopy,
- nextcopy,j+f+1,n+1,firstskel->ilaw);
- makeimage(nextskel,rel);
- deleteline(rel);
- }
- else if(nextskel!=nextimage)
- {
- makeimage(nextskel,firstrel);
- }
-
- image = firstskel->next;
- for(i=1;i<=f;i++)
- {
- deleteline(image->skeleton);
- image->skeleton = imagebetween(firstskel->skeleton,
- nextskel->skeleton,i,f+1,firstskel->ilaw);
- deleteline(image->outline);
- image->outline = imagebetween(firstskel->outline,
- nextskel->outline,i,f+1,firstskel->ilaw);
-
- if(skelable==TRUE)
- {
- rel = imagebetween(firstcopy,
- nextcopy,j+i,n+1,firstskel->ilaw);
- makeimage(image,rel);
- deleteline(rel);
- }
- else
- {
- makeimage(image,firstrel);
- }
- image = image->next;
- }
-
- j = j+f+1;
- firstskel = nextskel;
-
- nextskel = findtype(firstskel->next,SKELETON|XOUTLINE,&f);
- }
-
- if(skelable==TRUE)
- {
- deleteline(firstcopy);
- deleteline(nextcopy);
- }
- else
- nextrel=NULL;
-
- deleteline(firstrel);
- firstrel = nextrel;
-
- if(j<n)
- {
- n = n - j;
- firstcopy = copyline(firstskel->image);
- nextcopy = copyline(nextimage->image);
- preprocess(firstcopy,nextcopy);
- image = firstskel->next;
- for(i=1;i<=n;i++)
- {
- deleteline(image->image);
- image->image = imagebetween(firstcopy,
- nextcopy,i,n+1,firstskel->ilaw);
- image = image->next;
- }
- deleteline(firstcopy);
- deleteline(nextcopy);
- }
- }
- else
- {
- /* inbetweening of images */
- firstcopy = copyline(firstimage->image);
- nextcopy = copyline(nextimage->image);
-
- preprocess(firstcopy,nextcopy);
- image = firstimage->next;
- for(i=1;i<=n;i++)
- {
- deleteline(image->image);
- image->image = imagebetween(firstcopy,
- nextcopy,i,n+1,firstimage->ilaw);
- image = image->next;
- }
- deleteline(firstcopy);
- deleteline(nextcopy);
-
- if((nextimage->entry&(SKELETON|XOUTLINE))==(SKELETON|XOUTLINE))
- {
- skelable = TRUE;
- deleteline(firstrel);
- firstrel = makerelative(nextimage);
- }
- }
-
- firstimage = nextimage;
-
- nextimage = findtype(firstimage->next,IMAGE,&n);
- }
-
- if((firstimage->next!=NULL) && (skelable==TRUE))
- {
- firstskel = firstimage;
- nextskel = findtype(firstimage->next,SKELETON|XOUTLINE,&f);
- while(nextskel!=NULL)
- {
-
- makeimage(nextskel,firstrel);
-
- image = firstskel->next;
- for(i=1;i<=f;i++)
- {
- deleteline(image->skeleton);
- image->skeleton = imagebetween(firstskel->skeleton,
- nextskel->skeleton,i,f+1,firstskel->ilaw);
- deleteline(image->outline);
- image->outline = imagebetween(firstskel->outline,
- nextskel->outline,i,f+1,firstskel->ilaw);
- makeimage(image,firstrel);
- image = image->next;
- }
-
- firstskel = nextskel;
- nextskel = findtype(firstskel->next,SKELETON|XOUTLINE,&f);
- }
- }
- deleteline(firstrel);
- }
-
-